<template>
  <div>
    <div class="flex-wrap">
      <div class="oss-upload">
        <slot></slot>
        <label v-if="!disabled" class="hand">
          <input
            :multiple="multiple"
            type="file"
            class="hidden"
            @change="change"
          />
        </label>
      </div>

      <el-button
        v-if="!disabled && onDelete && value"
        @click="handleDelete"
        type="text"
        size="small"
        >删除</el-button
      >

      <slot name="tips">
        <span class="tips">{{ tips }}</span>
      </slot>
    </div>
    <draggable
      class="drag-list"
      v-if="!disabled && showFileList && filelist.length > 0"
      v-model="filelist"
      @change="drag"
    >
      <div class="drag-item" v-for="(item, idx) in filelist" :key="idx">
        <img class="drag-item-img" :src="item" />
        <i class="el-icon-error" @click="remove(idx)"></i>
      </div>
    </draggable>
    <template v-else-if="showFileList && filelist.length > 0">
      <div class="drag-list">
        <div class="drag-item" v-for="(item, idx) in filelist" :key="idx">
          <img class="drag-item-img" :src="item" />
        </div>
      </div>
    </template>
  </div>
</template>

<script>
import draggable from "vuedraggable";
import { uploadOSS, defaultLimit } from "@/utils/ossUpload";
export default {
  components: {
    draggable,
  },
  props: {
    value: String,
    limit: [String, Number],
    maxCount: [String, Number],
    tips: String,
    disabled: {
      type: Boolean,
      default: false,
    },
    compress: {
      type: Boolean,
      default: false,
    },
    showUploadResult: {
      type: Boolean,
      default: true,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    showFileList: {
      type: Boolean,
      default: false,
    },
    fileList: {
      type: Array,
      default: () => [],
    },
    onBeforeUpload: {
      type: Function,
      default: () => {},
    },
    onSuccess: {
      type: Function,
      default: () => {},
    },
    onError: {
      type: Function,
      default: () => {},
    },
    onChange: {
      type: Function,
      default: () => {},
    },
    onDelete: {
      type: Function,
      default: null,
    },
    dir: {
      type: String,
      default: "file",
    },
  },
  watch: {
    fileList: {
      handler(val) {
        this.filelist = val || [];
      },
      immediate: true,
    },
  },
  data() {
    return {
      filelist: [],
    };
  },
  methods: {
    clearFileList() {
      this.filelist = [];
    },
    handleDelete() {
      this.onDelete && this.onDelete();
    },
    remove(index) {
      this.filelist = this.filelist.filter((item, idx) => idx !== index);
      this.onChange(this.filelist);
    },
    drag() {
      this.onChange(this.filelist);
    },
    change(e) {
      const files = Array.from(e.target.files);
      const limit = Number(this.limit);
      const maxCount = Number(this.maxCount);
      if (maxCount === maxCount) {
        // maxCount值有效，则限制数量
        if (this.filelist.length + files.length > maxCount) {
          this.$message.warning(`最多上传${maxCount}张图片`);
          return;
        }
      }
      // 限制图片类型
      const _files = files.filter((d) => {
        if (d.type == "image/png" || d.type == "image/jpeg") {
          return true;
        } else {
          return false;
        }
      });
      e.target.value = null;

      // 存在不符合的图片类型
      if (_files.length !== files.length) {
        this.$message.warning("图片类型不是png或者jpeg");
      }
      // 没有有效的图片直接返回
      if (_files.length === 0) {
        return;
      }
      this.onBeforeUpload(); // 上传前钩子
      uploadOSS(_files, this.dir, {
        limitSize: isNaN(limit) ? defaultLimit : limit,
        compress: this.compress,
      })
        .then(({ result, code, msg }) => {
          this.showUploadResult &&
            this.$message({
              type: code == 1 ? "success" : "warning",
              message: msg,
            });
          result.forEach((res) => {
            this.filelist.push(res.url);
          });

          if (this.multiple || this.filelist[this.filelist.length - 1]) {
            this.onSuccess(
              result,
              this.multiple
                ? this.filelist
                : this.filelist[this.filelist.length - 1]
            );
          }
        })
        .catch((err) => {
          console.error(err);
          this.onError(err);
        });
    },
  },
};
</script>

<style scoped>
.oss-upload img {
  display: block;
}
.flex-wrap {
  display: inline-flex;
  align-items: center;
}
.oss-upload {
  display: inline-block;
  position: relative;
  margin-right: 10px;
}
.hand {
  z-index: 99;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.hidden {
  display: none;
}

.el-icon-error {
  position: absolute;
  right: -7px;
  top: -7px;
  font-size: 18px;
  cursor: pointer;
  color: #f56c6c;
}
.drag-list {
  display: flex;
  flex-wrap: wrap;
  padding: 20px 0;
}
.drag-item {
  position: relative;
  margin-right: 10px;
}

.drag-item-img {
  object-fit: contain;
  width: 100px;
  height: 100px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.tips {
  font-size: 12px;
  color: #999;
}
</style>